package functors;

import domain.Point;
import util.ShuduUtil;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Author: sszheng
 * @Date: 2018/8/6 16:49
 */
public class RestPointFunctor implements  Functor {
    @Override
    public Boolean calc( List<Point> list) {
        Boolean flag = Boolean.FALSE;
        for(Point point: list) {
            if(point.getValue() == 0) {
                flag = flag | calcPointFromRestPoint(point, list);
            }
        }
        return flag;
    }

    private Boolean calcPointFromRestPoint(Point point, List<Point> list) {
        Set<Set<Point>> pointSet = new HashSet<>();
        Set<Point> veSet = new HashSet<>();
        Set<Point> hoSet = new HashSet<>();
        Set<Point> partSet = new HashSet<>();
        Set<Point> allSet = new HashSet<>();
        for(Point point1: list) {
            if(point1.equals(point)) {
                continue;
            }
            if(point1.getX() == point.getX() && point1.getValue() == 0) {
                hoSet.add(point1);
                allSet.add(point1);
            }
            if(point1.getY() == point.getY() && point1.getValue() == 0) {
                veSet.add(point1);
                allSet.add(point1);
            }
            if(ShuduUtil.isPart(point, point1) && point1.getValue() == 0) {
                partSet.add(point1);
                allSet.add(point1);
            }
        }

        pointSet.add(veSet);
        pointSet.add(hoSet);
        pointSet.add(partSet);
        pointSet.add(allSet);

        for(Set<Point> set: pointSet) {
            Integer value = calcPointFromRestPoint(point.getPossibleValue(), set);
            if(value != null) {
                point.setValue(value);
                return Boolean.TRUE;
            }
        }

        return Boolean.FALSE;
    }

    private Integer calcPointFromRestPoint(Set<Integer> possibleValue, Set<Point> pointSet) {
        Set<Integer> set = new HashSet<>();
        for(Point point1 : pointSet) {
            if(point1.getPossibleValue() == null ) {
                return null;
            }
            set.addAll(point1.getPossibleValue());
        }
        if(set.size() == pointSet.size()) {
            possibleValue.removeAll(set);
            return ShuduUtil.getUniqueValue(possibleValue);
        }
        return null;
    }
}
